#include "interface.h"
#include <gr_graph_fun.h>

#include "graph.h"

static GnomeUIInfo file2_menu_uiinfo[] =
{
/*
  {
    GNOME_APP_UI_ITEM, "_Save",
    "Save graph as XGMML",
    (gpointer) saveXGMML_menu, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, "gtk-save",
    0, (GdkModifierType) 0, NULL
  },
*/
  {
    GNOME_APP_UI_ITEM, "Save _As",
    "Save graph as an XGMML file",
    (gpointer) graphSaveAs, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, "gtk-save-as",
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_SEPARATOR,
  GNOMEUIINFO_MENU_CLOSE_ITEM (gtk_widget_destroy, NULL),
  GNOMEUIINFO_END
};

static GnomeUIInfo edit2_menu_uiinfo[] =
{
  {
    GNOME_APP_UI_ITEM, "_Find",
    "Find node on the graph",
    (gpointer) gtk_false, NULL, NULL,
    GNOME_APP_PIXMAP_STOCK, "gtk-find",
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_SEPARATOR,
  GNOMEUIINFO_MENU_PROPERTIES_ITEM (gtk_false, NULL),
  GNOMEUIINFO_END
};

static GnomeUIInfo itemDraw_menu_uiinfo[] =
{
  {
    GNOME_APP_UI_ITEM, "_Random",
    "Place nodes randomly",
    (gpointer) graphDrawRandom, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_SEPARATOR,
  {
    GNOME_APP_UI_ITEM, "_Circular",
    "Place nodes in a circle",
    (gpointer) graphDrawCircular, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  {
    GNOME_APP_UI_ITEM, "_Diagonal",
    "Place nodes on a diagonal line",
    (gpointer) graphDrawDiagonal, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  {
    GNOME_APP_UI_ITEM, "_Horizontal",
    "Place nodes along a horizontal line",
    (gpointer) graphDrawHorizontal, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_SEPARATOR,
  {
    GNOME_APP_UI_ITEM, "_Force Directed",
    "Place nodes as if they were charged particles",
    (gpointer) graphDrawForceDirected, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_SEPARATOR,
  {
    GNOME_APP_UI_ITEM, "_Tree",
    "Organize nodes as a tree from a given node",
    (gpointer) graphDrawTree, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_END
};

static GnomeUIInfo help2_menu_uiinfo[] =
{
  GNOMEUIINFO_HELP ("w3live"),
  GNOMEUIINFO_MENU_ABOUT_ITEM (showAbout, NULL),
  GNOMEUIINFO_END
};

static GnomeUIInfo menubar2_uiinfo[] =
{
  GNOMEUIINFO_MENU_FILE_TREE (file2_menu_uiinfo),
  {
    GNOME_APP_UI_SUBTREE, "_Draw",
    "Graph Drawing Mode",
    itemDraw_menu_uiinfo, NULL, NULL,
    GNOME_APP_PIXMAP_NONE, NULL,
    0, (GdkModifierType) 0, NULL
  },
  GNOMEUIINFO_MENU_HELP_TREE (help2_menu_uiinfo),
  GNOMEUIINFO_END
};

GtkWidget*
create_graph (char *xgmml)
{
  GtkWidget *graph;
  GtkWidget *bonobodock2;
  GtkWidget *vbox4;
  GtkWidget *handleboxTools;
  GtkWidget *toolbarGraph;
  GtkWidget *buttonSave;
  GtkWidget *buttonFont;
  GtkWidget *buttonColor;
  GtkWidget *hbox5;
  GtkWidget *imageZoom;
  GtkWidget *hscaleScale;
  GtkWidget *scrolledwindow1;
  GtkWidget *canvasGraph;
  GtkWidget *appbarGraph;
  GraphFrame **graphptr = NULL;
  double x0,y0,x1,y1;
  graph_options *opts = NULL;

  graph = gnome_app_new ("W3live", "w3live - graph");
  gtk_window_set_default_size (GTK_WINDOW (graph), 640, 480);
  gtk_window_set_destroy_with_parent (GTK_WINDOW (graph), TRUE);

  bonobodock2 = GNOME_APP (graph)->dock;
  gtk_widget_show (bonobodock2);

  itemDraw_menu_uiinfo[0].user_data = (void *)graph;    // drawing options
  itemDraw_menu_uiinfo[2].user_data = (void *)graph;
  itemDraw_menu_uiinfo[3].user_data = (void *)graph;
  itemDraw_menu_uiinfo[4].user_data = (void *)graph;
  itemDraw_menu_uiinfo[6].user_data = (void *)graph;
  itemDraw_menu_uiinfo[8].user_data = (void *)graph;
  file2_menu_uiinfo[0].user_data    = (void *)graphptr; // save as
  file2_menu_uiinfo[2].user_data    = (void *)graph;    // close


  gnome_app_create_menus (GNOME_APP (graph), menubar2_uiinfo);

  vbox4 = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox4);
  gnome_app_set_contents (GNOME_APP (graph), vbox4);

  handleboxTools = gtk_handle_box_new ();
  gtk_widget_show (handleboxTools);
  gtk_box_pack_start (GTK_BOX (vbox4), handleboxTools, FALSE, TRUE, 0);
  gtk_handle_box_set_shadow_type (GTK_HANDLE_BOX (handleboxTools), GTK_SHADOW_NONE);

  toolbarGraph = gtk_toolbar_new ();
  gtk_widget_show (toolbarGraph);
  gtk_container_add (GTK_CONTAINER (handleboxTools), toolbarGraph);
  gtk_container_set_border_width (GTK_CONTAINER (toolbarGraph), 5);
  gtk_toolbar_set_style (GTK_TOOLBAR (toolbarGraph), GTK_TOOLBAR_ICONS);

  buttonSave = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbarGraph),
                                "gtk-save",
                                "Save Graph as XGMML",
                                NULL, NULL, NULL, -1);
  buttonFont = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbarGraph),
                                "gtk-select-font",
                                "Select Graph Label Font",
                                NULL, NULL, NULL, -1);
  
  buttonColor = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbarGraph),
                                "gtk-select-color",
                                "Select Node/Edge Color",
                                NULL, NULL, NULL, -1);

  gtk_widget_show (buttonSave);
  gtk_widget_show (buttonColor);

  hbox5 = gtk_hbox_new (FALSE, 2);
  gtk_widget_show (hbox5);
  gtk_toolbar_append_space (GTK_TOOLBAR (toolbarGraph));

  gtk_toolbar_append_widget (GTK_TOOLBAR (toolbarGraph), hbox5, NULL, NULL);
  gtk_container_set_border_width (GTK_CONTAINER (hbox5), 5);

  imageZoom = gtk_image_new_from_stock ("gtk-zoom-in", GTK_ICON_SIZE_LARGE_TOOLBAR);
  gtk_widget_show (imageZoom);
  gtk_box_pack_start (GTK_BOX (hbox5), imageZoom, FALSE, FALSE, 0);

  hscaleScale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (50, 1, 200, 1, 10, 0)));
  gtk_widget_show (hscaleScale);
  gtk_box_pack_start (GTK_BOX (hbox5), hscaleScale, FALSE, TRUE, 0);
  gtk_widget_set_usize (hscaleScale, 150, -2);
  gtk_scale_set_draw_value (GTK_SCALE (hscaleScale), FALSE);
  gtk_range_set_update_policy (GTK_RANGE (hscaleScale),GTK_UPDATE_DELAYED);

  scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (scrolledwindow1);
  gtk_box_pack_start (GTK_BOX (vbox4), scrolledwindow1, TRUE, TRUE, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  canvasGraph = gnome_canvas_new ();
  gtk_widget_show (canvasGraph);
  gtk_container_add (GTK_CONTAINER (scrolledwindow1), canvasGraph);
  gnome_canvas_set_scroll_region (GNOME_CANVAS (canvasGraph), 0, 0, 100, 100);

  appbarGraph = gnome_appbar_new (TRUE, TRUE, GNOME_PREFERENCES_NEVER);
  gtk_widget_show (appbarGraph);
  gnome_app_set_statusbar (GNOME_APP (graph), appbarGraph);

  gnome_app_install_menu_hints (GNOME_APP (graph), menubar2_uiinfo);

  gtk_signal_connect (GTK_OBJECT(buttonFont), "clicked",
		  GTK_SIGNAL_FUNC(display_font_select),
		  (void *)graph);
  
  gtk_signal_connect (GTK_OBJECT(buttonColor), "clicked",
		  GTK_SIGNAL_FUNC(display_color_select),
		  (void *)graph);
  
  gtk_signal_connect (GTK_OBJECT (hscaleScale), "value_changed",
			GTK_SIGNAL_FUNC (graphSetScale),
			(void *)graph);

	if(!(graphptr = (GraphFrame **)malloc(sizeof(GraphFrame *))))
		perror_exit("%s:%d ",__FILE__,__LINE__);
	*graphptr = NULL;

	gnome_canvas_get_scroll_region((GnomeCanvas *)canvasGraph,&x0,&y0,&x1,&y1);
	*graphptr = init_graph((int)x1,(int)y1);

	if(parse_xml_text_graph(*graphptr,xgmml,strlen(xgmml))) {
		gtk_widget_show(create_conn_fail("Could not understand graph"));
		return;
	}

	opts = init_options();
	draw_graph((GnomeCanvas *)canvasGraph,*graphptr,opts);
  
  
  /* Store pointers to all widgets, for use by lookup_widget(). */
  GLADE_HOOKUP_OBJECT_NO_REF (graph, graph, "graph");
  GLADE_HOOKUP_OBJECT_NO_REF (graph, graphptr, "graphptr");
  GLADE_HOOKUP_OBJECT_NO_REF (graph, opts, "graph_opts");
  GLADE_HOOKUP_OBJECT (graph, bonobodock2, "bonobodock2");
  GLADE_HOOKUP_OBJECT (graph, menubar2_uiinfo[0].widget, "file2");
  GLADE_HOOKUP_OBJECT (graph, file2_menu_uiinfo[0].widget, "save3");
  GLADE_HOOKUP_OBJECT (graph, file2_menu_uiinfo[1].widget, "save_as3");
  GLADE_HOOKUP_OBJECT (graph, file2_menu_uiinfo[2].widget, "separator6");
  GLADE_HOOKUP_OBJECT (graph, file2_menu_uiinfo[3].widget, "closeGraph");
  GLADE_HOOKUP_OBJECT (graph, menubar2_uiinfo[1].widget, "edit2");
  GLADE_HOOKUP_OBJECT (graph, edit2_menu_uiinfo[0].widget, "find1");
  GLADE_HOOKUP_OBJECT (graph, edit2_menu_uiinfo[1].widget, "separator15");
  GLADE_HOOKUP_OBJECT (graph, edit2_menu_uiinfo[2].widget, "properties2");
  GLADE_HOOKUP_OBJECT (graph, menubar2_uiinfo[2].widget, "itemDraw");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[0].widget, "drawRandom");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[1].widget, "separator32");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[2].widget, "drawCircular");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[3].widget, "drawDiagonal");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[4].widget, "drawHorizontal");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[5].widget, "separator33");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[6].widget, "drawForceDirected");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[7].widget, "separator34");
  GLADE_HOOKUP_OBJECT (graph, itemDraw_menu_uiinfo[8].widget, "drawTree");
  GLADE_HOOKUP_OBJECT (graph, menubar2_uiinfo[3].widget, "help2");
  GLADE_HOOKUP_OBJECT (graph, help2_menu_uiinfo[1].widget, "about5");
  GLADE_HOOKUP_OBJECT (graph, vbox4, "vbox4");
  GLADE_HOOKUP_OBJECT (graph, handleboxTools, "handleboxTools");
  GLADE_HOOKUP_OBJECT (graph, toolbarGraph, "toolbarGraph");
  GLADE_HOOKUP_OBJECT (graph, buttonSave, "buttonSave");
  GLADE_HOOKUP_OBJECT (graph, buttonFont, "buttonFont");
  GLADE_HOOKUP_OBJECT (graph, buttonFont, "buttonColor");
  GLADE_HOOKUP_OBJECT (graph, hbox5, "hbox5");
  GLADE_HOOKUP_OBJECT (graph, imageZoom, "imageZoom");
  GLADE_HOOKUP_OBJECT (graph, hscaleScale, "hscaleScale");
  GLADE_HOOKUP_OBJECT (graph, scrolledwindow1, "scrolledwindow1");
  GLADE_HOOKUP_OBJECT (graph, canvasGraph, "canvasGraph");
  GLADE_HOOKUP_OBJECT (graph, appbarGraph, "appbarGraph");

	return graph;
}

void
graphSave                              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
graphSaveAs                            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GraphFrame **graphptr = (GraphFrame **)user_data;
	gtk_widget_show(create_fileselectionXGMML(graphptr));
}

void
display_font_select                     (GtkWidget     *button,
                                         gpointer      user_data)
{
	GtkWidget *graph = (GtkWidget *)user_data;
	gtk_widget_show(create_font_select(graph));
}

void
display_color_select                    (GtkWidget     *button,
                                         gpointer      user_data)
{
	GtkWidget *graph = (GtkWidget *)user_data;
	gtk_widget_show(create_color_select(graph));
}


void
graphDrawRandom                        (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GtkWidget *graph;
	GnomeCanvas *canvas;
	GraphFrame **graphptr;
	graph_options *opts;
	
	graph    = (GtkWidget *)user_data;
	canvas   = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	opts     = (graph_options *)lookup_widget(graph,"graph_opts");

	compute_random_positions(*graphptr);
	draw_graph(canvas,*graphptr,opts);

}


void
graphDrawCircular                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GtkWidget *graph;
	GnomeCanvas *canvas;
	GraphFrame **graphptr;
	graph_options *opts;
	
	graph    = (GtkWidget *)user_data;
	canvas   = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	opts     = (graph_options *)lookup_widget(graph,"graph_opts");

	compute_circular_positions(*graphptr);
	draw_graph(canvas,*graphptr,opts);
}


void
graphDrawDiagonal                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GtkWidget *graph;
	GnomeCanvas *canvas;
	GraphFrame **graphptr;
	graph_options *opts;
	

	graph    = (GtkWidget *)user_data;
	canvas   = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	opts     = (graph_options *)lookup_widget(graph,"graph_opts");

	compute_diagonal_positions(*graphptr);
	draw_graph(canvas,*graphptr,opts);
}


void
graphDrawHorizontal                    (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GtkWidget *graph;
	GnomeCanvas *canvas;
	GraphFrame **graphptr;
	graph_options *opts;
	

	graph    = (GtkWidget *)user_data;
	canvas   = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	opts     = (graph_options *)lookup_widget(graph,"graph_opts");

	compute_horizontal_positions(*graphptr);
	draw_graph(canvas,*graphptr,opts);
}


void
graphDrawForceDirected                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GtkWidget *graph;
	GnomeCanvas *canvas;
	GraphFrame **graphptr;
	graph_options *opts;
	

	graph    = (GtkWidget *)user_data;
	canvas   = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	opts     = (graph_options *)lookup_widget(graph,"graph_opts");

	compute_force_directed_positions(*graphptr);
	draw_graph(canvas,*graphptr,opts);
}


void
graphDrawTree                          (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
graphSetScale                          (GtkRange        *range,
                                        gpointer         user_data)
{
	double x0,y0,x1,y1;
	GtkWidget *graph = (GtkWidget *)user_data;
	GnomeCanvas *canvas = (GnomeCanvas *)lookup_widget(graph,"canvasGraph");
	GraphFrame **graphptr = (GraphFrame **)lookup_widget(graph,"graphptr");
	gnome_canvas_set_pixels_per_unit(canvas,((gtk_range_get_value(range))/50.0));
	gnome_canvas_get_scroll_region(canvas,&x0,&y0,&x1,&y1);
	(*graphptr)->wp = (*graphptr)->w = (int)x1;
	(*graphptr)->hp = (*graphptr)->h = (int)y1;
}

void
saveXGMML_menu                         (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	GraphFrame **graphptr = (GraphFrame **)user_data;
	gtk_widget_show(create_fileselectionXGMML(graphptr));
}
